/*
 *  Pyramide.cpp
 *  Ray Tracing
 *
 *  Created by Jean-Marc Comby + Romain Dequesne on Tue Jun 08 2004.
 *  Copyright (c) 2004. All rights reserved.
 *
 */

#include "Pyramide.hpp"

using namespace std;

/**
 * Constructeur initialisant les 5 instances de Plan nécessaire.
 *
 * @param base1 un des sommets de la base.
 * @param base2 un des sommets de la base.
 * @param base3 un des sommets de la base.
 * @param hauteur sommet de la Pyramide.
 */
Pyramide::Pyramide(const Coord& base1, const Coord& base2, const Coord& base3,
		   const Coord& hauteur)
{
  Vecteur Pbase1(base1,base2),Pbase2(base1,base3);
  Vecteur tmp( Pbase2+Pbase1 );
  Coord base4( base1 + tmp ); // 4 eme coord de la base
  cout << "4ème pt de la base : " << base4 << endl;
  Vecteur Pbase3(base4,base3), Pbase4(base4,base2);
  Vecteur arrete1(base1,hauteur),arrete4(base4,hauteur);
  Vecteur vNormal1(Pbase1^Pbase2); // normal de la base pyramide
  if (vNormal1*arrete1>0)
    vNormal1*=-1;
  Vecteur vNormal2(Pbase1^arrete1);
  if (vNormal2*vNormal1>0)
    vNormal2*=-1;
  Vecteur vNormal3(Pbase2^arrete1);
  if (vNormal3*vNormal1>0)
    vNormal3*=-1;
  Vecteur vNormal4(Pbase3^arrete4);
  if (vNormal4*vNormal1>0)
    vNormal4*=-1;
  Vecteur vNormal5(Pbase4^arrete4);
  if (vNormal5*vNormal1>0)
    vNormal5*=-1;
  // 5 plans qui composent la pyramide
  listplan.push_back(Plan::SharedPtr (new Plan(vNormal1,base1)));
  listplan.push_back(Plan::SharedPtr (new Plan(vNormal2,hauteur)));
  listplan.push_back(Plan::SharedPtr (new Plan(vNormal3,hauteur)));
  listplan.push_back(Plan::SharedPtr (new Plan(vNormal4,hauteur)));
  listplan.push_back(Plan::SharedPtr (new Plan(vNormal5,hauteur)));
  // on prend l'intersection des plans
  listFC.push_back(FormeComposee::SharedPtr (new FormeComposee(inter,listplan[0].get(),listplan[1].get())));
  listFC.push_back(FormeComposee::SharedPtr (new FormeComposee(inter,listplan[2].get(),listplan[3].get())));
  listFC.push_back(FormeComposee::SharedPtr (new FormeComposee(inter,listplan[4].get(),listFC[0].get())));
  form[0]=listFC[1].get();
  form[1]=listFC[2].get();
  op=inter;

  Nom = "Pyramide";
  PseudoCentre = base1 + .5 * tmp
    + 1. / 3. * ( vNormal1 * arrete1 ) / vNormal1.norme() * vNormal1;

  /**
   * Pour trouver les coordonnées de PseudoCentre on détermine quelle
   * est la "grande diagonale" de la base. On travaille alors dans le
   * triangle formé par la grande diagonale et le sommet de la
   * pyramide. On détermine alors la position du cercle circonscrit à
   * ce triangle.
   */
  Coord a;
  Coord b( hauteur );
  Coord m( base1 + .5 * tmp );
  if ( Vecteur( PseudoCentre, base1 ).norme() >
       Vecteur( PseudoCentre, base2 ).norme() )
    a = base1;
  else
    a = base2;
    
  Vecteur arete( a, b );
  VecteurU dirPlan( m, a );
  Plan aide( m, dirPlan );

  VecteurU norm( arete ^ dirPlan );
  VecteurU dirRayon( arete ^ norm );
  if ( dirRayon * dirPlan > 0 )
    dirRayon *= -1.;

  PseudoCentre = aide.trouveIntersection( Rayon( a + 0.5 * arete, dirRayon ) );
  PseudoRayon = sqrt( Vecteur( a, PseudoCentre ).norme() );
}

/**
 * Le destructeur n'a rien de spécial à faire.
 */
Pyramide::~Pyramide()
{}
